<template>
  <el-container style="height: 100vh">
    <el-header class="head-bg-color">
      <!-- logo部分 -->
      <el-row>
        <el-col :span="24">
          <img src="../assets/logo.png" class="logo" />
        </el-col>
        <el-col :span="24">
          <img src="../assets/text-logo-purple.png" class="logo-text" />
        </el-col>
      </el-row>
      <el-row>
        <el-button
          @click="dialogVisible = true"
          icon="el-icon-edit"
          circle
          style="background-color: rgba(255, 255, 255, 0.05)"
        ></el-button>

        <el-dialog
          title="历史检索记录"
          :visible.sync="dialogVisible"
          width="30%"
          style="text-align: left; line-height: 10px"
          :before-close="save_history"
        >
          <div style="overflow-y: scroll; height: 150px">
            <div v-show="history_is_null">
              <p>历史检索记录为空</p>
            </div>
            <el-tag
              v-for="tag in history"
              :key="tag.value"
              closable
              :disable-transitions="false"
              @close="handleClose(tag)"
            >
              {{
                tag.value.length > 15
                  ? tag.value.substring(0, 14) + "......"
                  : tag.value
              }}
            </el-tag>
          </div>

          <span slot="footer" class="dialog-footer">
            <el-button
              type="info"
              plain
              @click="is_sure"
              :disabled="history_is_null"
              >一键删除</el-button
            >
          </span>
        </el-dialog>

        <el-autocomplete
          class="input-box"
          v-model="question"
          :fetch-suggestions="querySearch"
          placeholder="请输入问题"
          @keyup.enter.native="send_question"
          clearable
        ></el-autocomplete>
        <el-button
          type="primary"
          round
          icon="el-icon-search"
          :disabled="ban_click"
          @click="send_question"
          >检 索</el-button
        >
      </el-row>
    </el-header>
    <el-main>
      <el-row :gutter="20">
        <el-col :span="6">
          <div class="grid-content bg-purple">
            <transition name="fade">
              <loading v-if="isLoading"></loading>
            </transition>

            <img
              src="../assets/title/title-system-desc.png"
              class="demonstration"
            />

            <el-tabs type="border-card" class="module-container">
              <el-tab-pane label="系统说明" class="content-desc">
                <p>
                  &nbsp;&nbsp;&nbsp;&nbsp;本系统为基于语义解析的知识图谱检索系统。知识库为包含44,112个实体和30万条关系的医疗领域知识图谱。
                </p>
                <kgecharts></kgecharts>
              </el-tab-pane>
              <el-tab-pane label="可提问类型">
                <el-table
                  :data="tableData"
                  height="280"
                  border
                  style="width: 100%"
                >
                  <el-table-column prop="index" label="编号" width="40">
                  </el-table-column>
                  <el-table-column prop="type" label="问题类型" width="100">
                  </el-table-column>
                  <el-table-column prop="example" label="例句">
                  </el-table-column>
                </el-table>
              </el-tab-pane>
            </el-tabs>
          </div>
        </el-col>
        <el-col :span="8">
          <div class="grid-content bg-purple">
            <img
              src="../assets/title/title-search-answer.png"
              class="demonstration"
            />
            <div class="module-container">
              <descriptions
                id="desc"
                :entities="entities"
                :relations="relations"
              ></descriptions>

              <!-- 卡片样式，用于展示文本答案 -->
              <el-card class="box-card">
                <div slot="header" class="clearfix">
                  <span>检索结果 [耗时：{{ elapsed_time }} s]</span>
                </div>
                <div style="overflow-y: scroll; max-height: 150px">
                  <div style="text-align: left; margin: 5px; line-height: 20px">
                    {{ answer == "" ? "暂无结果" : answer }}
                  </div>
                </div>
              </el-card>
            </div>
          </div>
        </el-col>
        <el-col :span="10">
          <div class="grid-content bg-purple">
            <img
              src="../assets/title/title-kg-show.png"
              class="demonstration"
            />
            <el-empty
              description="暂无数据"
              :image-size="200"
              v-show="!show_graph"
            ></el-empty>
            <graphs
              v-if="show_graph"
              :nodes="nodes"
              :edges="edges"
              @node-click="ClickNode"
            ></graphs>
          </div>
        </el-col>
      </el-row>
    </el-main>
  </el-container>
</template>

<script>
import Loading from "@/components/loading";
import kgecharts from "./Echarts";
import descriptions from "./Descriptions";
import graphs from "./Graphs";

export default {
  name: "KgSearch",
  components: { Loading, kgecharts, descriptions, graphs },
  data() {
    return {
      question: "", // 自然语言问题
      elapsed_time: 0, // 查询时间
      ban_click: false, // 按钮是否禁止点击
      isLoading: false,
      dialogVisible: false, // 历史记录dialog表单是否展示
      tableData: [
        {
          index: 1,
          type: "疾病描述",
          example: "胃痉挛",
        },
        {
          index: 2,
          type: "已知疾病问症状",
          example: "乳腺癌的症状有哪些？",
        },
        {
          index: 3,
          type: "已知症状找疾病",
          example: "最近老流鼻涕怎么办？",
        },
        {
          index: 4,
          type: "疾病病因",
          example: "为什么有的人会失眠？",
        },
        {
          index: 5,
          type: "疾病并发症",
          example: "中枢神经系统淋巴瘤有啥并发症？",
        },
        {
          index: 6,
          type: "疾病忌口食物",
          example: "啥食物是甲状腺癌病人不能吃的？",
        },
        {
          index: 7,
          type: "疾病建议食物",
          example: "耳鸣病人吃点啥好？",
        },
        {
          index: 8,
          type: "食物对什么病人有害",
          example: "哪些人最好不好吃蜂蜜？",
        },
        {
          index: 9,
          type: "食物对什么病人有益",
          example: "鹅肉有什么好处？",
        },
        {
          index: 10,
          type: "疾病对症药物",
          example: "肝病要吃什么药？",
        },
        {
          index: 11,
          type: "药品治疗病症",
          example: "板蓝根颗粒能治什么病？",
        },
        {
          index: 12,
          type: "疾病所需检查",
          example: "脑膜炎怎么才能查出来？",
        },
        {
          index: 13,
          type: "检查能查病症",
          example: "全血细胞计数能查出啥来？",
        },
        {
          index: 14,
          type: "疾病预防措施",
          example: "怎样才能预防肾虚？",
        },
        {
          index: 15,
          type: "疾病治疗周期",
          example: "哮喘要多久才能好？",
        },
        {
          index: 16,
          type: "疾病治疗方式",
          example: "高血压要怎么治？",
        },
        {
          index: 17,
          type: "疾病治疗概率",
          example: "小儿白血病能治好嘛？",
        },
        {
          index: 18,
          type: "疾病易感人群",
          example: "什么人更容易得麦收皮炎？",
        },
        {
          index: 19,
          type: "疾病主治科室",
          example: "得了宫颈湿疣看什么科室？",
        },
        {
          index: 20,
          type: "科室治疗疾病",
          example: "皮肤科主要治疗的疾病有什么？",
        },
        {
          index: 21,
          type: "判断‘疾病-症状’关系",
          example: "颅骨骨髓炎会引起回吸性涕血吗？",
        },
        {
          index: 22,
          type: "判断‘疾病-科室’关系",
          example: "外阴湿疹是到皮肤科挂号治疗吗？",
        },
        {
          index: 23,
          type: "判断‘疾病-食物’关系",
          example: "鹅肉适合先天性巨输尿管的人吃吗？",
        },
        {
          index: 24,
          type: "判断‘疾病-药物’关系",
          example: "芪斛楂颗粒可以治疗色汗症吗？",
        },
        {
          index: 25,
          type: "判断‘疾病-检查’关系",
          example: "脑血管硬化要做面神经检查咩？",
        },
        {
          index: 26,
          type: "判断‘疾病-疾病’（并发症）关系",
          example: "肺不张和百日咳是什么关系？",
        },
        {
          index: 27,
          type: "药物在售药品",
          example: "人血白蛋白的在售药品是啥？",
        },
        {
          index: 28,
          type: "单意图简单并列句",
          example: "肺不张和毛囊炎的常见症状是啥？",
        },
        {
          index: 29,
          type: "询问两种疾病的相同症状",
          example: "湿疹和毛囊炎有啥相同的症状？",
        },
        {
          index: 30,
          type: "询问同时具备两种症状的疾病",
          example: "同时具备脓疱和出血性丘疹这些症状的疾病是什么？",
        },
        {
          index: 31,
          type: "比较两疾病之间的治愈率",
          example: "毛囊炎和湿疹哪个治愈率更高？",
        },
        {
          index: 32,
          type: "比较两疾病之间的治疗周期",
          example: "前列腺炎和小儿尿石症的治疗时间哪个更久？",
        },
      ],
      entities: [],
      relations: [],
      answer: "", //检索答案
      show_graph: false, // 是否展示知识图谱
      nodes: [], // 知识图谱节点
      edges: [], // 知识图谱边
      history: [],
      history_is_change: false, // 判断用户是否删除了历史记录
    };
  },
  computed: {
    history_is_null() {
      return this.history == null || this.history.length == 0;
    },
  },
  methods: {
    ClickNode(data) {
      // 子组件出发节点点击事件，父组件修改对应变量
      // alert(data);
      this.question = data;
    },
    querySearch(queryString, cb) {
      var history = this.history;
      if (history != null) {
        var results = queryString
          ? history.filter(this.createFilter(queryString))
          : history;
      } else {
        results = [];
      }

      console.log(results);
      // 调用 callback 返回建议列表的数据
      cb(results);
    },
    createFilter(queryString) {
      return (history) => {
        return (
          history.value.toLowerCase().indexOf(queryString.toLowerCase()) >= 0 // === 0 则为句首匹配
        );
      };
    },
    duplicate_check(item, arr) {
      if(arr == null){
        return -1
      }
      for (var i = 0; i < arr.length; i++) {
        if (item == arr[i].value) {
          return i;
        }
      }
      return -1;
    },
    handleClose(tag) {
      // tag为对象{value: xxx}
      // console.log(tag);
      let that = this;
      this.$confirm("是否确认删除？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.$message({
            type: "success",
            message: "删除成功!",
          });
          that.history.splice(that.history.indexOf(tag), 1);
          that.history_is_change = true;
        })
      
    },
    save_history(done) {
      if (this.history_is_change) {
        localStorage.setItem("history", JSON.stringify(this.history));
        this.history_is_change = false;
      }
      done();
    },
    is_sure() {
      let that = this;
      this.$confirm("此操作将删除所有历史记录, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.$message({
            type: "success",
            message: "删除成功!",
          });
          that.history = [];
        })
        .catch(() => {
          // this.$message({
          //   type: 'info',
          //   message: '已取消删除'
          // });
        });
    },
    send_question() {
      //设置按钮禁用，避免重复点击
      let that = this;
      this.ban_click = true;
      setTimeout(function () {
        that.ban_click = false;
      }, 1000);
      if (this.question.length == 0 || this.question.trim() == "") {
        // 输入为空或全是空格，则弹出警报
        this.$message({
          message: "输入不能为空哦",
          type: "warning",
        });
      } else {
        // 进行查询
        this.isLoading = true; // loading
        let input = this.question;
        var startstamp = new Date().valueOf();

        // 请求并处理数据
        this.$axios
          .post(
            "/hello",
            {
              question: input,
            },
            {
              timeout: 60000, // 超时60s则报错
            }
          )
          .then((response) => {
            this.answer = "";
            this.isLoading = false;
            this.elapsed_time = new Date().valueOf() - startstamp;
            this.elapsed_time = (this.elapsed_time / 1000).toFixed(2); //ms -> s 并保留两位小数
            // 数据格式转换
            var json = new Function("return " + response.data)();
            console.log("json", json);
            let ans_isnull = false;
            if (json.answer.length == 0) {
              ans_isnull = true;
              // 警告
              this.$notify({
                title: "警告",
                message: "未查询到匹配结果！",
                type: "warning",
              });
            }
            for (var i = 0; i < json.answer.length; i++) {
              this.answer += json.answer[i];
            }

            this.entities = json.entities;
            this.relations = json.relations;

            this.nodes = json.KG.nodes;
            this.edges = json.KG.edges;

            // 展示图谱
            if (this.nodes.length > 0) {
              this.show_graph = true;
            } else {
              this.show_graph = false;
            }

            // 历史记录
            if (!ans_isnull) {
              if(this.history == null){
                this.history = [];
              }
              let id = this.duplicate_check(input, this.history); // 重复性检查
              if (id < 0) {
                if (this.history.length >= 100) {
                  this.history.pop(); //删除数组尾部元素
                }
              } else {
                this.history.splice(id, 1);
              }
              this.history.unshift({ value: input }); // 将元素添加到数组头部
            }
          })
          .catch((response) => {
            // 清空所有
            this.isLoading = false;
            this.answer = "";
            this.entities = [];
            this.relations = [];
            this.show_graph = false;

            let msg = "error！";
            console.log(response);
            if (response.response == undefined) {
              // 可能是SyntaxError啥的
              // this.$notify({
              //   title: "警告",
              //   message: "未查询到匹配结果！",
              //   type: "warning",
              // });
              this.$notify.error({
                title: "错误",
                message: String(response),
              });
            } else if (response.response.status) {
              let status = response.response.status.toString();
              if (
                response.response.status > 499 &&
                response.response.status < 506
              ) {
                msg = " 服务端响应异常！";
              } else if (
                response.response.status > 399 &&
                response.response.status < 418
              ) {
                msg = " 客户端请求异常！";
              }
              this.$notify.error({
                title: status + " 错误",
                message: msg,
              });
            } else {
              this.$notify.error({
                title: "错误",
                message: String(response),
              });
            }
          });
      }
    },
  },
  mounted() {
    // 页面首次进入时加载缓存数据
    var list = localStorage.getItem("history");
    if (list === "{}") {
      console.log("---缓存为空[来自KgSearch的打印]---");
    } else {
      this.history = JSON.parse(list);
    }

    // this.history = list?list:history;
    let that = this;
    // 关闭或刷新浏览器窗口时触发(有return或者有须要执行的事件才会触发弹窗)
    window.onbeforeunload = function (e) {
      // 保存历史记录
      localStorage.setItem("history", JSON.stringify(that.history));
    };
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1,
h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}

.el-header {
  text-align: center;
  line-height: 60px;
  min-height: 35vh;
}

.el-main {
  /* background-color: #e9eef3; */
  color: #333;
  text-align: center;
  line-height: 10px; /* 块级元素之间的行间隔 */
  min-height: 65vh;
}

body > .el-container {
  margin-bottom: 40px;
}

.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
  line-height: 260px;
}

.el-container:nth-child(7) .el-aside {
  line-height: 320px;
}

.head-bg-color {
  background: #e8cbc0; /* fallback for old browsers */
  background: -webkit-linear-gradient(
    to right,
    #636fa4,
    #e8cbc0
  ); /* Chrome 10-25, Safari 5.1-6 */
  background: linear-gradient(
    to right,
    #636fa4,
    #e8cbc0
  ); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
.logo {
  width: 60px;
  height: auto;
  padding-top: 10px;
}
.logo-text {
  /* 是设置width不设置height则图片会等比例缩放 */
  width: 300px;
  height: 50px;
}

.el-row {
  margin-bottom: 0px;
}
.el-row:last-child {
  margin-bottom: 0;
}

/* 设置自己输入框的样式 */
.input-box {
  width: 500px;
}
.input-box >>> .el-input__inner {
  /*或者 /deep/ .el-input__inner  */
  background: rgba(0, 0, 0, 0.1); /*调整inner的背景色，透明*/
  border-radius: 20px; /*输入框圆角值*/
  color: azure;
}
.grid-content {
  border-radius: 8px;
  min-height: 58vh;
  height: 58vh;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.fade-enter,
.fade-leave-active {
  opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s;
}

.demonstration {
  width: 100px;
  height: auto;
}

.content-desc {
  text-align: left;
  line-height: 20px;
  /* white-space: pre; */
}

/* main中三个模块中的容器 */
.module-container {
  margin: 10px;
  max-height: 350px;
  min-height: 350px;
}

/* 第二个模块中展示文本答案的卡片样式 */
.clearfix {
  text-align: left;
}
.text {
  font-size: 14px;
  text-align: left;
}

.item {
  margin-bottom: 18px;
}

.clearfix:before,
.clearfix:after {
  display: table;
  content: "";
}
.clearfix:after {
  clear: both;
}

.box-card {
  width: 100%;
  margin-top: 10px;
}

/* '.el-tag + .el-tag'是除第一个标签以外的 */
.el-tag {
  /* margin-left: 50px; */
  margin-top: 5px;
  margin-right: 5px;
}
</style>
